﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ParserCore;

namespace TestParser
{
    [TestClass]
    public class StatementToStringTest
    {
        [TestMethod]
        public void SingleExpressionStatementToStringTest()
        {
            var ses = new SingleExpressionStatement(new Identifier("a"));
            var str1 = "a";
            var str2 = "b";

            Assert.AreEqual(ses.ToString(), str1);
            Assert.AreNotEqual(ses.ToString(), str2);
        }

        [TestMethod]
        public void AssignmentStatementToStringTest()
        {
            var ast1 = new AssignmentStatement(
                new Expression[] {
                                new Identifier("a"),
                                new Identifier("c")
                            },
                new Constant("5")
                );
            var ast2 = new AssignmentStatement(
                new Expression[] {
                                new Identifier("a"),
                            },
                new Constant("5")
                );
            var ast3 = new AssignmentStatement(
                new Expression[] { },
                new Constant("5")
                );

            var str1 = "[a,c]=5";
            var str2 = "[a]=5";
            var str3 = "[]=5";

            Assert.AreEqual(ast1.ToString(), str1);
            Assert.AreEqual(ast2.ToString(), str2);
            Assert.AreEqual(ast3.ToString(), str3);
        }

        [TestMethod]
        public void BlockStatementToStringTest()
        {
            var bs1 = new BlockStatement(
                new SingleExpressionStatement(new Identifier("a1")),
                new SingleExpressionStatement(new Identifier("a2")),
                new SingleExpressionStatement(new Identifier("a3"))
                );
            var bs2 = new BlockStatement(
                new SingleExpressionStatement(new Constant("5"))
                );
            var bs3 = new BlockStatement();

            var str1 = "a1;a2;a3";
            var str2 = "5";
            var str3 = "";

            Assert.AreEqual(bs1.ToString(), str1);
            Assert.AreEqual(bs2.ToString(), str2);
            Assert.AreEqual(bs3.ToString(), str3);
        }

        [TestMethod]
        public void IfThenElseStatementToStringTest()
        {
            var exp = new Constant("1");
            var stt = new SingleExpressionStatement(new Identifier("a"));
            var stf = new SingleExpressionStatement(new Identifier("b"));
            var ifts = new IfThenElseStatement(exp, stt, stf);

            var str = "if(1){a}else{b}";

            Assert.AreEqual(ifts.ToString(), str);
        }

        [TestMethod]
        public void SwitchCaseStatementToStringTest()
        {
            var scs = new SwitchCaseStatement(
                new Identifier("a"),
                new SingleExpressionStatement(new Identifier("b")),
                new Tuple<Expression, Statement>[] {
                    new Tuple<Expression,Statement>(
                        new Identifier("a1"),
                        new SingleExpressionStatement(new Identifier("b1"))
                    ),
                    new Tuple<Expression,Statement>(
                        new Identifier("a2"),
                        new SingleExpressionStatement(new Identifier("b2"))
                    ),
                    new Tuple<Expression,Statement>(
                        new Identifier("a3"),
                        new SingleExpressionStatement(new Identifier("b3"))
                    )
                });

            var str = "switch(a)case(a1){b1}case(a2){b2}case(a3){b3}otherwise{b}";

            Assert.AreEqual(scs.ToString(), str);

        }

        [TestMethod]
        public void ForStatementToStringTest()
        {
            var fs = new ForStatement(
                new Identifier("a"),
                new Identifier("b"),
                new SingleExpressionStatement(new Identifier("c"))
                );
            var str = "for(a=b){c}";

            Assert.AreEqual(fs.ToString(), str);
        }

        [TestMethod]
        public void WhileStatementToStringTest()
        {
            var ws = new WhileStatement(
                new Constant("1"),
                new SingleExpressionStatement(new Identifier("a"))
                );
            var str = "while(1){a}";

            Assert.AreEqual(ws.ToString(), str);
        }

        [TestMethod]
        public void TryCatchStatementToStringTest()
        {
            var tcs = new TryCatchStatement(
                new SingleExpressionStatement(new Identifier("t")),
                new Identifier("e"),
                new SingleExpressionStatement(new Identifier("c"))
                );
            var str = "try{t}catch(e){c}";

            Assert.AreEqual(tcs.ToString(), str);
        }

        [TestMethod]
        public void FunctionDefinitionStatementToStringTest()
        {
            var id1 = new Identifier[]{
                    new Identifier("a"),
                    new Identifier("b"),
                    new Identifier("c")
                };
            var id2 = new Identifier[] { new Identifier("a") };
            var id3 = new Identifier[] { };

            var fds1 = new FunctionDefinitionStatement(
                new Identifier("fun"),
                id1,
                id1,
                new SingleExpressionStatement(new Identifier("d"))
            );
            var fds2 = new FunctionDefinitionStatement(
                new Identifier("fun"),
                id1,
                id2,
                new SingleExpressionStatement(new Identifier("d"))
            );
            var fds3 = new FunctionDefinitionStatement(
                new Identifier("fun"),
                id1,
                id3,
                new SingleExpressionStatement(new Identifier("d"))
            );
            var fds4 = new FunctionDefinitionStatement(
                new Identifier("fun"),
                id2,
                id1,
                new SingleExpressionStatement(new Identifier("d"))
            );
            var fds5 = new FunctionDefinitionStatement(
                new Identifier("fun"),
                id3,
                id1,
                new SingleExpressionStatement(new Identifier("d"))
            );

            var str1 = "function[a,b,c]=fun(a,b,c){d}";
            var str2 = "function[a,b,c]=fun(a){d}";
            var str3 = "function[a,b,c]=fun(){d}";
            var str4 = "function[a]=fun(a,b,c){d}";
            var str5 = "function[]=fun(a,b,c){d}";

            Assert.AreEqual(fds1.ToString(), str1);
            Assert.AreEqual(fds2.ToString(), str2);
            Assert.AreEqual(fds3.ToString(), str3);
            Assert.AreEqual(fds4.ToString(), str4);
            Assert.AreEqual(fds5.ToString(), str5);

        }

        [TestMethod]
        public void GlobalDeclarationStatementToStringTest()
        {
            var ds1 = new GlobalDeclarationStatement(
                    new Identifier("a1"),
                    new Identifier("a2"),
                    new Identifier("a3")
               );
            var ds2 = new GlobalDeclarationStatement(new Identifier("a1"));
            var ds3 = new GlobalDeclarationStatement();

            var str1 = "global(a1,a2,a3)";
            var str2 = "global(a1)";
            var str3 = "global()";

            Assert.AreEqual(ds1.ToString(), str1);
            Assert.AreEqual(ds2.ToString(), str2);
            Assert.AreEqual(ds3.ToString(), str3);
        }

        [TestMethod]
        public void PersistentDeclarationStatementToStringTest()
        {
            var ds1 = new PersistentDeclarationStatement(
                    new Identifier("a1"),
                    new Identifier("a2"),
                    new Identifier("a3")
               );
            var ds2 = new PersistentDeclarationStatement(new Identifier("a1"));
            var ds3 = new PersistentDeclarationStatement();

            var str1 = "persistent(a1,a2,a3)";
            var str2 = "persistent(a1)";
            var str3 = "persistent()";

            Assert.AreEqual(ds1.ToString(), str1);
            Assert.AreEqual(ds2.ToString(), str2);
            Assert.AreEqual(ds3.ToString(), str3);
        }

    }

}
